<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
    />
    <title>快捷录音</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/ffmpeg/0.11.6/ffmpeg.min.js"></script>
    <style>
      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
        font-family: 'SF Pro Display', 'PingFang SC', 'Helvetica Neue', Arial,
          sans-serif;
      }

      :root {
        --primary-bg: #e6e7ee;
        --secondary-bg: #ffffff;
        --shadow-light: #ffffff;
        --shadow-dark: #d1d9e6;
        --accent-color: #667eea;
        --accent-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        --success-color: #4ecdc4;
        --danger-color: #ff6b6b;
        --text-primary: #2d3748;
        --text-secondary: #718096;
        --recording-pulse: #ff4757;
      }

      body {
        background: var(--primary-bg);
        color: var(--text-primary);
        min-height: 100vh;
        padding: 20px;
        padding-bottom: 80px;
        transition: all 0.3s ease;
      }

      .container {
        max-width: 600px;
        margin: 0 auto;
        padding: 30px;
        background: var(--primary-bg);
        border-radius: 30px;
        box-shadow: 20px 20px 60px var(--shadow-dark),
          -20px -20px 60px var(--shadow-light);
        transition: all 0.3s ease;
      }

      .container:hover {
        box-shadow: 25px 25px 70px var(--shadow-dark),
          -25px -25px 70px var(--shadow-light);
      }

      /* 拟态风格卡片 */
      .neumorphic-card {
        background: var(--primary-bg);
        border-radius: 20px;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
        transition: all 0.3s ease;
      }

      .neumorphic-inset {
        background: var(--primary-bg);
        border-radius: 20px;
        box-shadow: inset 8px 8px 16px var(--shadow-dark),
          inset -8px -8px 16px var(--shadow-light);
        transition: all 0.3s ease;
      }

      /* 转换弹窗样式 */
      .conversion-dialog {
        display: none;
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(230, 231, 238, 0.9);
        backdrop-filter: blur(10px);
        z-index: 1000;
        align-items: center;
        justify-content: center;
        animation: fadeIn 0.4s ease;
      }

      .conversion-dialog-content {
        background: var(--primary-bg);
        padding: 30px;
        border-radius: 25px;
        width: 90%;
        max-width: 400px;
        text-align: center;
        box-shadow: 15px 15px 30px var(--shadow-dark),
          -15px -15px 30px var(--shadow-light);
        animation: slideUp 0.4s ease;
      }

      @keyframes slideUp {
        from {
          opacity: 0;
          transform: translateY(30px) scale(0.9);
        }
        to {
          opacity: 1;
          transform: translateY(0) scale(1);
        }
      }

      .conversion-progress {
        margin: 25px 0;
      }

      .conversion-progress-bar {
        width: 100%;
        height: 12px;
        background: var(--primary-bg);
        border-radius: 20px;
        overflow: hidden;
        box-shadow: inset 4px 4px 8px var(--shadow-dark),
          inset -4px -4px 8px var(--shadow-light);
      }

      .conversion-progress-inner {
        height: 100%;
        background: var(--accent-gradient);
        border-radius: 20px;
        width: 0%;
        transition: width 0.3s ease;
        box-shadow: 0 2px 10px rgba(102, 126, 234, 0.3);
      }

      .conversion-progress-text {
        margin-top: 15px;
        font-size: 16px;
        font-weight: 600;
        color: var(--accent-color);
      }

      .conversion-buttons {
        display: flex;
        justify-content: center;
        gap: 15px;
        margin-top: 25px;
      }

      .conversion-btn {
        padding: 12px 24px;
        border: none;
        border-radius: 25px;
        cursor: pointer;
        font-weight: 600;
        transition: all 0.3s ease;
        background: var(--primary-bg);
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
      }

      .conversion-cancel {
        color: var(--danger-color);
      }

      .conversion-cancel:hover {
        box-shadow: inset 6px 6px 12px var(--shadow-dark),
          inset -6px -6px 12px var(--shadow-light);
        transform: scale(0.98);
      }

      /* 头部样式 */
      header {
        text-align: center;
        margin-bottom: 40px;
        padding: 25px;
        background: var(--primary-bg);
        border-radius: 25px;
        box-shadow: 10px 10px 20px var(--shadow-dark),
          -10px -10px 20px var(--shadow-light);
        animation: headerFloat 0.8s ease;
      }

      @keyframes headerFloat {
        from {
          opacity: 0;
          transform: translateY(-20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      h1 {
        font-size: 32px;
        margin-bottom: 15px;
        font-weight: 700;
        background: var(--accent-gradient);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
        animation: titleGlow 2s ease-in-out infinite alternate;
      }

      @keyframes titleGlow {
        from {
          filter: brightness(1);
        }
        to {
          filter: brightness(1.1);
        }
      }

      .status {
        font-size: 16px;
        color: var(--text-secondary);
        margin: 15px 0;
        text-align: center;
        min-height: 24px;
        font-weight: 500;
        transition: all 0.3s ease;
      }

      .status.recording {
        color: var(--recording-pulse);
        animation: pulse 1.5s ease-in-out infinite;
      }

      @keyframes pulse {
        0%,
        100% {
          opacity: 1;
        }
        50% {
          opacity: 0.6;
        }
      }

      .timer {
        font-size: 28px;
        font-weight: 700;
        text-align: center;
        margin: 20px 0;
        font-family: 'SF Mono', 'Monaco', monospace;
        letter-spacing: 3px;
        color: var(--accent-color);
        text-shadow: 0 2px 10px rgba(102, 126, 234, 0.3);
        transition: all 0.3s ease;
      }

      .timer.active {
        animation: timerPulse 1s ease-in-out infinite;
      }

      @keyframes timerPulse {
        0%,
        100% {
          transform: scale(1);
        }
        50% {
          transform: scale(1.05);
        }
      }

      /* 可视化器样式 */
      .visualizer {
        width: 100%;
        height: 140px;
        margin: 30px 0;
        overflow: hidden;
        position: relative;
        background: var(--primary-bg);
        border-radius: 25px;
        box-shadow: inset 12px 12px 24px var(--shadow-dark),
          inset -12px -12px 24px var(--shadow-light);
        animation: visualizerAppear 0.6s ease 0.2s both;
      }

      @keyframes visualizerAppear {
        from {
          opacity: 0;
          transform: scale(0.9);
        }
        to {
          opacity: 1;
          transform: scale(1);
        }
      }

      .waveform {
        position: absolute;
        bottom: 0;
        left: 0;
        width: 100%;
        height: 100%;
        display: flex;
        align-items: flex-end;
        justify-content: center;
        padding: 15px;
      }

      .bar {
        width: 4px;
        margin: 0 1px;
        background: var(--accent-gradient);
        border-radius: 2px;
        box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
        transition: all 0.1s ease;
      }

      /* 控制按钮样式 */
      .controls {
        display: flex;
        justify-content: center;
        gap: 20px;
        margin: 40px 0;
        animation: controlsSlide 0.8s ease 0.4s both;
      }

      @keyframes controlsSlide {
        from {
          opacity: 0;
          transform: translateY(20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .btn {
        padding: 16px 28px;
        font-size: 16px;
        font-weight: 600;
        border: none;
        border-radius: 25px;
        cursor: pointer;
        transition: all 0.3s ease;
        display: flex;
        align-items: center;
        justify-content: center;
        min-width: 140px;
        background: var(--primary-bg);
        color: var(--text-primary);
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
        position: relative;
        overflow: hidden;
      }

      .btn::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(
          90deg,
          transparent,
          rgba(255, 255, 255, 0.2),
          transparent
        );
        transition: left 0.5s;
      }

      .btn:hover::before {
        left: 100%;
      }

      .btn:disabled {
        opacity: 0.5;
        cursor: not-allowed;
        box-shadow: 4px 4px 8px var(--shadow-dark),
          -4px -4px 8px var(--shadow-light);
      }

      .btn-primary {
        background: var(--accent-gradient);
        color: white;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2);
      }

      .btn-danger {
        background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
        color: white;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2);
      }

      .btn-success {
        background: linear-gradient(135deg, #4ecdc4 0%, #44a08d 100%);
        color: white;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2);
      }

      .btn:hover:not(:disabled) {
        transform: translateY(-2px);
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
      }

      .btn:active:not(:disabled) {
        transform: translateY(0);
        box-shadow: inset 6px 6px 12px var(--shadow-dark),
          inset -6px -6px 12px var(--shadow-light);
      }

      /* 录音记录样式 */
      .recordings-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin: 40px 0 25px;
        padding: 20px 25px;
        background: var(--primary-bg);
        border-radius: 20px;
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
        animation: headerSlide 0.6s ease 0.6s both;
      }

      @keyframes headerSlide {
        from {
          opacity: 0;
          transform: translateX(-20px);
        }
        to {
          opacity: 1;
          transform: translateX(0);
        }
      }

      .recordings-header h2 {
        font-size: 20px;
        font-weight: 600;
        color: var(--text-primary);
      }

      .recordings-list {
        display: flex;
        flex-direction: column;
        gap: 20px;
      }

      .recording-item {
        background: var(--primary-bg);
        border-radius: 20px;
        padding: 20px;
        display: flex;
        align-items: center;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
        transition: all 0.3s ease;
        animation: itemSlideIn 0.5s ease;
      }

      @keyframes itemSlideIn {
        from {
          opacity: 0;
          transform: translateY(20px) scale(0.95);
        }
        to {
          opacity: 1;
          transform: translateY(0) scale(1);
        }
      }

      .recording-item:hover {
        transform: translateY(-3px);
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
      }

      .recording-info {
        flex-grow: 1;
      }

      .recording-title {
        font-weight: 600;
        margin-bottom: 8px;
        color: var(--text-primary);
        font-size: 16px;
      }

      .recording-details {
        display: flex;
        font-size: 14px;
        color: var(--text-secondary);
        gap: 20px;
      }

      .recording-actions {
        display: flex;
        gap: 12px;
      }

      .action-btn {
        width: 44px;
        height: 44px;
        border-radius: 50%;
        border: none;
        background: var(--primary-bg);
        color: var(--text-primary);
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        transition: all 0.3s ease;
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
        font-size: 14px;
        font-weight: 600;
      }

      .action-btn:hover {
        transform: scale(1.1) translateY(-2px);
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
      }

      .action-btn:active {
        transform: scale(0.95);
        box-shadow: inset 4px 4px 8px var(--shadow-dark),
          inset -4px -4px 8px var(--shadow-light);
      }

      .play-btn {
        color: var(--success-color);
      }

      .download-webm-btn {
        color: var(--accent-color);
      }

      .download-mp3-btn {
        color: var(--accent-color);
        font-size: 10px;
      }

      .delete-btn {
        color: var(--danger-color);
      }

      .no-recordings {
        text-align: center;
        padding: 60px 20px;
        color: var(--text-secondary);
        font-style: italic;
        font-size: 16px;
        background: var(--primary-bg);
        border-radius: 20px;
        box-shadow: inset 8px 8px 16px var(--shadow-dark),
          inset -8px -8px 16px var(--shadow-light);
      }

      .clear-btn {
        background: var(--primary-bg);
        border: none;
        color: var(--danger-color);
        padding: 8px 16px;
        border-radius: 20px;
        font-size: 14px;
        font-weight: 600;
        cursor: pointer;
        transition: all 0.3s ease;
        box-shadow: 4px 4px 8px var(--shadow-dark),
          -4px -4px 8px var(--shadow-light);
      }

      .clear-btn:hover {
        box-shadow: inset 4px 4px 8px var(--shadow-dark),
          inset -4px -4px 8px var(--shadow-light);
        transform: scale(0.98);
      }

      footer {
        text-align: center;
        margin-top: 40px;
        font-size: 14px;
        color: var(--text-secondary);
        padding: 20px;
        background: var(--primary-bg);
        border-radius: 20px;
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
        animation: footerFade 0.8s ease 0.8s both;
      }

      @keyframes footerFade {
        from {
          opacity: 0;
        }
        to {
          opacity: 1;
        }
      }

      /* 响应式设计 */
      @media (max-width: 500px) {
        .container {
          padding: 20px;
          margin: 10px;
        }

        .controls {
          flex-direction: column;
          align-items: center;
        }

        .btn {
          width: 100%;
          max-width: 300px;
        }

        .recording-actions {
          gap: 8px;
        }

        .action-btn {
          width: 38px;
          height: 38px;
          font-size: 12px;
        }

        h1 {
          font-size: 24px;
        }

        .timer {
          font-size: 24px;
        }
      }

      /* 暗色模式支持 */
      @media (prefers-color-scheme: dark) {
        :root {
          --primary-bg: #2d3748;
          --secondary-bg: #1a202c;
          --shadow-light: #4a5568;
          --shadow-dark: #1a202c;
          --text-primary: #f7fafc;
          --text-secondary: #a0aec0;
        }
      }

      /* 动画优化 */
      @media (prefers-reduced-motion: reduce) {
        *,
        *::before,
        *::after {
          animation-duration: 0.01ms !important;
          animation-iteration-count: 1 !important;
          transition-duration: 0.01ms !important;
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <header>
        <h1>🎙️ 智能录音助手</h1>
        <div class="status" id="status">准备就绪</div>
        <div class="timer" id="timer">00:00</div>
      </header>

      <div class="visualizer">
        <div class="waveform" id="waveform"></div>
      </div>

      <div class="controls">
        <button id="startBtn" class="btn btn-primary">🎤 开始录音</button>
        <button id="stopBtn" class="btn btn-danger" disabled>
          ⏹️ 停止录音
        </button>
        <button id="pauseBtn" class="btn btn-success" disabled>
          ⏸️ 暂停录音
        </button>
      </div>

      <div class="recordings-header">
        <h2>📁 录音记录</h2>
        <button id="clearBtn" class="clear-btn">🗑️ 清空记录</button>
      </div>

      <div class="recordings-list" id="recordingsList">
        <div class="no-recordings">暂无录音记录</div>
      </div>

      <footer>
        <p>🔒 支持移动端浏览器 | 录音存储在本地 | 保护用户隐私</p>
      </footer>
    </div>

    <!-- 转换弹窗 -->
    <div id="conversion-dialog" class="conversion-dialog">
      <div class="conversion-dialog-content">
        <h3>🔄 正在转换为MP3</h3>
        <p
          style="
            font-size: 14px;
            margin: 15px 0;
            color: var(--danger-color);
            font-weight: 500;
          "
        >
          💡 提示：原始WebM格式下载更快且音质更好，建议优先保存
        </p>
        <div class="conversion-progress">
          <div class="conversion-progress-bar">
            <div
              class="conversion-progress-inner"
              id="conversion-progress-inner"
            ></div>
          </div>
          <div class="conversion-progress-text" id="conversion-progress-text">
            0%
          </div>
        </div>
        <div class="conversion-buttons">
          <button
            id="conversion-cancel"
            class="conversion-btn conversion-cancel"
          >
            ❌ 取消转换
          </button>
        </div>
      </div>
    </div>

    <script>
      // 页面加载时清空录音记录
      window.addEventListener('DOMContentLoaded', () => {
        localStorage.removeItem('audioRecordings')
        updateRecordingsList()
        document.getElementById('status').textContent =
          '首次进入，已清空历史记录'

        // 添加页面加载动画
        document.body.style.opacity = '0'
        setTimeout(() => {
          document.body.style.transition = 'opacity 0.5s ease'
          document.body.style.opacity = '1'
        }, 100)
      })

      // 获取DOM元素
      const startBtn = document.getElementById('startBtn')
      const stopBtn = document.getElementById('stopBtn')
      const pauseBtn = document.getElementById('pauseBtn')
      const clearBtn = document.getElementById('clearBtn')
      const statusEl = document.getElementById('status')
      const timerEl = document.getElementById('timer')
      const recordingsList = document.getElementById('recordingsList')
      const waveform = document.getElementById('waveform')

      // 转换弹窗元素
      const conversionDialog = document.getElementById('conversion-dialog')
      const conversionProgressInner = document.getElementById(
        'conversion-progress-inner'
      )
      const conversionProgressText = document.getElementById(
        'conversion-progress-text'
      )
      const conversionCancelBtn = document.getElementById('conversion-cancel')

      // 录音相关变量
      let mediaRecorder
      let audioChunks = []
      let audioContext
      let analyser
      let timerInterval
      let seconds = 0
      let isPaused = false
      let animationId

      // 转换状态变量
      let conversionInProgress = false
      let currentConversionIndex = null
      let ffmpegInstance = null

      // 创建音频分析器（保持原有功能不变）
      function createAnalyser(stream) {
        audioContext = new (window.AudioContext || window.webkitAudioContext)()
        analyser = audioContext.createAnalyser()
        const source = audioContext.createMediaStreamSource(stream)
        source.connect(analyser)
        analyser.fftSize = 256

        waveform.innerHTML = ''
        const bufferLength = analyser.frequencyBinCount
        const bars = 50
        const barWidth = waveform.offsetWidth / bars - 2

        for (let i = 0; i < bars; i++) {
          const bar = document.createElement('div')
          bar.className = 'bar'
          bar.style.height = '2px'
          bar.style.width = barWidth + 'px'
          waveform.appendChild(bar)
        }

        function updateWaveform() {
          if (
            !analyser ||
            !mediaRecorder ||
            mediaRecorder.state === 'inactive' ||
            isPaused
          ) {
            animationId = requestAnimationFrame(updateWaveform)
            return
          }

          const dataArray = new Uint8Array(bufferLength)
          analyser.getByteFrequencyData(dataArray)
          const bars = waveform.querySelectorAll('.bar')

          for (let i = 0; i < bars.length; i++) {
            const value = dataArray[i] || 0
            const percent = value / 256
            const height = Math.max(2, percent * 100)
            bars[i].style.height = height + 'px'
            bars[i].style.background = `linear-gradient(to top, 
                        rgba(${Math.floor(79 + percent * 176)}, ${Math.floor(
              172 + percent * 84
            )}, ${Math.floor(254 - percent * 84)}), 
                        rgba(${Math.floor(79 + percent * 176)}, ${Math.floor(
              172 + percent * 84
            )}, ${Math.floor(254 - percent * 84)}, 0.7))`
          }

          animationId = requestAnimationFrame(updateWaveform)
        }

        updateWaveform()
      }

      // 开始录音
      startBtn.addEventListener('click', async () => {
        statusEl.textContent = '正在请求麦克风权限...'
        statusEl.classList.add('recording')

        try {
          const stream = await navigator.mediaDevices.getUserMedia({
            audio: true,
          })
          statusEl.textContent = '🔴 正在录音...'
          timerEl.classList.add('active')

          mediaRecorder = new MediaRecorder(stream)
          audioChunks = []
          createAnalyser(stream)

          mediaRecorder.ondataavailable = (event) => {
            if (event.data.size > 0) {
              audioChunks.push(event.data)
            }
          }

          mediaRecorder.onstop = () => {
            const audioBlob = new Blob(audioChunks, { type: 'audio/webm' })
            saveRecording(audioBlob, seconds)
            stream.getTracks().forEach((track) => track.stop())

            clearInterval(timerInterval)
            seconds = 0
            timerEl.textContent = '00:00'
            timerEl.classList.remove('active')
            statusEl.classList.remove('recording')
            cancelAnimationFrame(animationId)
          }

          mediaRecorder.start()
          startBtn.disabled = true
          stopBtn.disabled = false
          pauseBtn.disabled = false
          startTimer()
        } catch (err) {
          console.error('录音错误:', err)
          statusEl.textContent = '❌ 无法访问麦克风，请确保已授予权限'
          statusEl.classList.remove('recording')
          startBtn.disabled = false
        }
      })

      // 停止录音
      stopBtn.addEventListener('click', () => {
        if (mediaRecorder && mediaRecorder.state !== 'inactive') {
          mediaRecorder.stop()
          statusEl.textContent = '✅ 录音已停止'
          statusEl.classList.remove('recording')
          startBtn.disabled = false
          stopBtn.disabled = true
          pauseBtn.disabled = true
          pauseBtn.innerHTML = '⏸️ 暂停录音'
          isPaused = false
        }
      })

      // 暂停/恢复录音
      pauseBtn.addEventListener('click', () => {
        if (!mediaRecorder) return

        if (mediaRecorder.state === 'recording') {
          mediaRecorder.pause()
          statusEl.textContent = '⏸️ 录音已暂停'
          pauseBtn.innerHTML = '▶️ 继续录音'
          isPaused = true
          clearInterval(timerInterval)
        } else if (mediaRecorder.state === 'paused') {
          mediaRecorder.resume()
          statusEl.textContent = '🔴 正在录音...'
          pauseBtn.innerHTML = '⏸️ 暂停录音'
          isPaused = false
          startTimer()
        }
      })

      // 清空录音记录
      clearBtn.addEventListener('click', () => {
        if (confirm('确定要清空所有录音记录吗？')) {
          localStorage.removeItem('audioRecordings')
          updateRecordingsList()
          statusEl.textContent = '🗑️ 录音记录已清空'
        }
      })

      // 保存录音到本地存储
      function saveRecording(blob, duration) {
        const reader = new FileReader()
        reader.readAsDataURL(blob)

        reader.onloadend = () => {
          const base64data = reader.result
          const recording = {
            data: base64data,
            timestamp: new Date().toISOString(),
            duration: duration,
          }

          const recordings =
            JSON.parse(localStorage.getItem('audioRecordings')) || []
          recordings.push(recording)

          if (recordings.length > 10) {
            recordings.shift()
          }

          localStorage.setItem('audioRecordings', JSON.stringify(recordings))
          updateRecordingsList()
        }
      }

      // 更新录音列表
      function updateRecordingsList() {
        const recordings =
          JSON.parse(localStorage.getItem('audioRecordings')) || []

        if (recordings.length === 0) {
          recordingsList.innerHTML =
            '<div class="no-recordings">📭 暂无录音记录</div>'
          return
        }

        recordingsList.innerHTML = ''

        recordings.reverse().forEach((rec, index) => {
          const date = new Date(rec.timestamp)
          const dateStr = date.toLocaleDateString()
          const timeStr = date.toLocaleTimeString([], {
            hour: '2-digit',
            minute: '2-digit',
          })
          const durationStr = formatTime(rec.duration)

          const recordingItem = document.createElement('div')
          recordingItem.className = 'recording-item'
          recordingItem.style.animationDelay = `${index * 0.1}s`
          recordingItem.innerHTML = `
                    <div class="recording-info">
                        <div class="recording-title">🎵 录音 ${
                          recordings.length - index
                        }</div>
                        <div class="recording-details">
                            <span>📅 ${dateStr} ${timeStr}</span>
                            <span>⏱️ 时长: ${durationStr}</span>
                        </div>
                    </div>
                    <div class="recording-actions">
                        <button class="action-btn play-btn" title="播放">
                            ▶️
                        </button>
                        <button class="action-btn download-webm-btn" title="下载WebM">
                            ⬇️
                        </button>
                        <button class="action-btn download-mp3-btn" title="下载MP3">
                            <small>MP3</small>
                        </button>
                        <button class="action-btn delete-btn" title="删除">
                            🗑️
                        </button>
                    </div>
                `

          // 添加事件监听器（保持原有功能）
          recordingItem
            .querySelector('.play-btn')
            .addEventListener('click', () => {
              playRecording(rec.data)
            })

          recordingItem
            .querySelector('.download-webm-btn')
            .addEventListener('click', () => {
              downloadRecording(rec.data, `recording-${index + 1}.webm`)
            })

          recordingItem
            .querySelector('.download-mp3-btn')
            .addEventListener('click', () => {
              if (
                confirm(
                  '转换为MP3格式需要时间且消耗更多资源。\n建议优先下载WebM格式（更快更省资源）\n\n是否继续转换为MP3？'
                )
              ) {
                currentConversionIndex = index
                convertToMP3(rec.data, index)
              }
            })

          recordingItem
            .querySelector('.delete-btn')
            .addEventListener('click', () => {
              if (confirm('确定要删除这条录音吗？')) {
                deleteRecording(index)
              }
            })

          recordingsList.appendChild(recordingItem)
        })
      }

      // 播放录音
      function playRecording(base64data) {
        const audio = new Audio(base64data)
        audio.play()
        statusEl.textContent = '🔊 正在播放录音...'
      }

      // 下载录音
      function downloadRecording(base64data, filename) {
        const link = document.createElement('a')
        link.href = base64data
        link.download = filename
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        statusEl.textContent = '📥 录音下载中...'
      }

      // Base64转换为Blob
      function base64ToBlob(base64) {
        const byteString = atob(base64.split(',')[1])
        const mimeString = base64.split(',')[0].split(':')[1].split(';')[0]
        const ab = new ArrayBuffer(byteString.length)
        const ia = new Uint8Array(ab)

        for (let i = 0; i < byteString.length; i++) {
          ia[i] = byteString.charCodeAt(i)
        }

        return new Blob([ab], { type: mimeString })
      }

      // WebM转换为MP3
      async function convertToMP3(base64Data, index) {
        if (conversionInProgress) {
          alert('当前已有转换任务在进行中，请稍后再试')
          return
        }

        conversionDialog.style.display = 'flex'
        conversionInProgress = true

        try {
          const { createFFmpeg, fetchFile } = FFmpeg
          ffmpegInstance = createFFmpeg({
            log: true,
            progress: ({ ratio }) => {
              const percent = Math.round(ratio * 100)
              conversionProgressInner.style.width = `${percent}%`
              conversionProgressText.textContent = `${percent}%`
            },
          })

          await ffmpegInstance.load()
          const webmBlob = base64ToBlob(base64Data)
          ffmpegInstance.FS(
            'writeFile',
            'input.webm',
            await fetchFile(webmBlob)
          )
          await ffmpegInstance.run(
            '-i',
            'input.webm',
            '-b:a',
            '64k',
            '-ac',
            '1',
            'output.mp3'
          )

          const mp3Data = ffmpegInstance.FS('readFile', 'output.mp3')
          const mp3Blob = new Blob([mp3Data.buffer], { type: 'audio/mp3' })
          const url = URL.createObjectURL(mp3Blob)
          const a = document.createElement('a')
          a.href = url
          a.download = `recording-${index + 1}.mp3`
          document.body.appendChild(a)
          a.click()
          document.body.removeChild(a)
          URL.revokeObjectURL(url)

          statusEl.textContent = '✅ MP3转换完成并已下载'
        } catch (error) {
          console.error('转换失败:', error)
          statusEl.textContent = '❌ MP3转换失败: ' + error.message
        } finally {
          conversionDialog.style.display = 'none'
          conversionInProgress = false
          ffmpegInstance = null
        }
      }

      // 取消转换
      conversionCancelBtn.addEventListener('click', () => {
        if (conversionInProgress) {
          conversionDialog.style.display = 'none'
          conversionInProgress = false
          statusEl.textContent = '❌ MP3转换已取消'
        }
      })

      // 删除录音
      function deleteRecording(index) {
        const recordings =
          JSON.parse(localStorage.getItem('audioRecordings')) || []
        const actualIndex = recordings.length - 1 - index

        if (actualIndex >= 0 && actualIndex < recordings.length) {
          recordings.splice(actualIndex, 1)
          localStorage.setItem('audioRecordings', JSON.stringify(recordings))
          updateRecordingsList()
          statusEl.textContent = '🗑️ 录音已删除'
        }
      }

      // 格式化时间
      function formatTime(totalSeconds) {
        const minutes = Math.floor(totalSeconds / 60)
        const seconds = totalSeconds % 60
        return `${minutes.toString().padStart(2, '0')}:${seconds
          .toString()
          .padStart(2, '0')}`
      }

      // 开始计时器
      function startTimer() {
        clearInterval(timerInterval)
        seconds = 0
        timerEl.textContent = '00:00'

        timerInterval = setInterval(() => {
          if (!isPaused) {
            seconds++
            timerEl.textContent = formatTime(seconds)
          }
        }, 1000)
      }

      // 浏览器兼容性检查
      if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
        statusEl.textContent =
          '❌ 您的浏览器不支持录音功能，请使用最新版Chrome、Firefox或Edge浏览器'
        startBtn.disabled = true
      }
    </script>
  </body>
</html>
